package javagamecontroller.components.joystick;

import java.util.ArrayList;
import javagamecontroller.connection.BluetoothMessenger;
import util.input.android.events.LineSegment;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import com.javagamecontroller.R;


/**
 * This class creates a touch screen that records touch events on the screen and
 * sends them to the messenger.
 * 
 * @author Ben Schwab
 * 
 */
public class TouchScreen extends SurfaceView implements Runnable, Callback {

    private final int FPS = 30;
    private final int DELAY = 1000 / FPS;
    private ArrayList<PaintSegment> myLineSegments = new ArrayList<PaintSegment>();
    private Paint myDrawPaint = new Paint();
    private Thread touchScreenThread = new Thread(this);
    private int myScreenWidth;
    private int myScreenHeight;
    private int previousX;
    private int previousY;
    private static int NEW_TOUCH = -1;
    private final int SEGMENT_DURATION = 2;
    private Paint myStartPaint;
    private BluetoothMessenger myMessenger;
    private BitmapDrawable touchScreenDrawable;

    public TouchScreen (Context context, AttributeSet attrs) {
        super(context, attrs);
        getHolder().addCallback(this);
        myStartPaint = new Paint();
        myStartPaint.setARGB(255, 0, 0, 0);
        myStartPaint.setStrokeWidth(8);
        this.setOnTouchListener(myDrawListener);
        previousX = NEW_TOUCH;
        previousY = NEW_TOUCH;
        myMessenger = BluetoothMessenger.getInstance();
        Resources resource = context.getResources();
        touchScreenDrawable =
                new BitmapDrawable(resource, BitmapFactory.decodeResource(resource,
                                                                          R.drawable.touch_screen));

    }

    @Override
    public void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {
        setSize(width, height);

    }

    @Override
    public void surfaceCreated (SurfaceHolder holder) {
        touchScreenThread.start();
        setSize(this.getWidth(), this.getHeight());
    }

    private void setSize (int width, int height) {
        myScreenWidth = width;
        myScreenHeight = height;
        touchScreenDrawable.setBounds(new Rect(0, 0, width, height));
    }

    @Override
    public void surfaceDestroyed (SurfaceHolder holder) {

    }

    @Override
    public void run () {
        long beforeTime;
        long timeDiff;
        long sleep;
        beforeTime = System.currentTimeMillis();
        while (true) {
            draw();
            timeDiff = System.currentTimeMillis() - beforeTime;
            sleep = DELAY - timeDiff;
            if (sleep < 0) {
                sleep = 2;
            }
            try {
                Thread.sleep(sleep);
            }
            catch (InterruptedException e) {

            }
            beforeTime = System.currentTimeMillis();
        }

    }

    public void draw () {
        Canvas canvas = this.getHolder().lockCanvas();
        if (canvas == null) { return; }
        touchScreenDrawable.draw(canvas);

        for (int i = myLineSegments.size() - 1; i >= 0; i--) {
            PaintSegment j = myLineSegments.get(i);
            canvas.drawLine(j.getStartX(), j.getStartY(), j.getEndX(), j.getEndY(), j.getPaint());
            if (j.incrementScreenDuration()) {
                myLineSegments.remove(j);
            }

        }

        this.getHolder().unlockCanvasAndPost(canvas);
    }

    private final OnTouchListener myDrawListener = new OnTouchListener() {
        @Override
        public boolean onTouch (View v, MotionEvent event) {

            int nextX = (int) event.getX();
            int nextY = (int) event.getY();
            if (previousX == NEW_TOUCH && previousY == NEW_TOUCH) {
                previousX = nextX;
                previousY = nextY;
            }
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    if ((int) event.getX() != previousX && (int) event.getY() != previousY) {
                        PaintSegment nextSegment =
                                new PaintSegment(previousX, previousY, nextX, nextY, myScreenWidth,
                                                 myScreenHeight, SEGMENT_DURATION, FPS,
                                                 myStartPaint);
                        myLineSegments.add(nextSegment);
                        LineSegment nextLineSegment =
                                new LineSegment(previousX, previousY, nextX, nextY, myScreenWidth,
                                                myScreenHeight);
                        previousX = nextX;
                        previousY = nextY;
                        myMessenger.write(nextLineSegment);
                    }

                    break;
                case MotionEvent.ACTION_DOWN:

                    break;
                case MotionEvent.ACTION_UP:
                    previousX = NEW_TOUCH;
                    previousY = NEW_TOUCH;

                    break;
            }
            return true;
        }

    };

}
